package com.carpedil.shirodemo.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.carpedil.shirodemo.common.exception.BizRuntimeException;
import com.carpedil.shirodemo.common.util.ResultCode;
import com.carpedil.shirodemo.common.util.ShiroPasswordSaltUtil;
import com.carpedil.shirodemo.common.util.TreeUtil;
import com.carpedil.shirodemo.system.mapper.UserMapper;
import com.carpedil.shirodemo.system.mapper.UserRoleMapper;
import com.carpedil.shirodemo.system.model.Menu;
import com.carpedil.shirodemo.system.model.User;
import com.carpedil.shirodemo.system.service.IMenuService;
import com.carpedil.shirodemo.system.service.IOperatorService;
import com.carpedil.shirodemo.system.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 用户表 服务实现类
 *
 * @author carpedil
 * @since 2021-01-05
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
  @Autowired private UserMapper userMapper;
  @Autowired private UserRoleMapper userRoleMapper;

  @Autowired private IMenuService menuService;

  @Autowired private IOperatorService operatorService;

  @Override
  public Set<String> selectRoleNameByUserName(String username) {
    return userMapper.selectRoleNameByUserName(username);
  }

  @Override
  public Set<String> selectPermsByUserName(String username) {
    Set<String> perms = new HashSet<>();
    List<Menu> menuTree = menuService.selectMenuTreeByUsername(username);
    List<Menu> leafNodeMenuList = TreeUtil.getAllLeafNode(menuTree);
    // 循环添加所有菜单权限
    for (Menu menu : leafNodeMenuList) {
      perms.add(menu.getPerms());
    }
    // 添加该用户所有操作权限
    perms.addAll(selectOperatorPermsByUserName(username));
    return perms;
  }

  @Override
  public Set<String> selectOperatorPermsByUserName(String username) {
    return userMapper.selectOperatorPermsByUserName(username);
  }

  @Override
  public User selectUserByUserName(String username) {
    return userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
  }

  @Override
  public IPage<User> selectAllWithDept(Integer page, Integer limit, User userQuery) {
    Page<User> pages = new Page<>((page - 1), limit);
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    if (userQuery != null) {
      queryWrapper.eq(
          userQuery.getUsername() != null && !"".equals(userQuery.getUsername()),
          "username",
          userQuery.getUsername());
      queryWrapper.eq(
          userQuery.getEmail() != null && !"".equals(userQuery.getEmail()),
          "email",
          userQuery.getEmail());
      queryWrapper.eq(userQuery.getStatus() != null, "status", userQuery.getStatus());
      queryWrapper.eq(userQuery.getDeptId() != null, "dept_id", userQuery.getDeptId());
      queryWrapper.eq("deleted", 0);
    }

    return userMapper.selectAllWithDept(pages, queryWrapper);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  /** 新增用户 1. 检查是否有重名用户 2. 加密加盐 3. 添加用户 4. 添加角色信息 */
  public boolean save(User user, Integer[] roleIds) {
    // 检查是否有重名用户
    checkUserNameOnCreate(user.getUsername());

    user.setSalt(ShiroPasswordSaltUtil.createSalt());
    user.setPassword(ShiroPasswordSaltUtil.md5Salt(user.getPassword(), user.getSalt()));
    int insert = userMapper.insert(user);
    if (insert > 0) {
      grantRole(user.getUserId(), roleIds);
    }
    return insert > 0;
  }

  private void checkUserNameOnCreate(String username) {
    Integer count = userMapper.selectCount(new QueryWrapper<User>().eq("username", username));
    if (count > 0) {
      throw new BizRuntimeException(ResultCode.USER_HAS_EXISTED);
    }
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean updateUser(User user, Integer[] roleIds) {
    int i = userMapper.update(user, new UpdateWrapper<User>().eq("user_id", user.getUserId()));
    if (i > 0) {
      i = grantRole(user.getUserId(), roleIds);
    }
    return i > 0;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean enable(Integer userId) {
    int i = userMapper.enable(userId);
    return i > 0;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean disable(Integer userId) {
    int i = userMapper.disable(userId);
    return i > 0;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean deleteUserById(Integer id) {
    return userMapper.deleteById(id) > 0;
  }

  private int grantRole(Integer userId, Integer[] roleIds) {
    // 清空用户原有角色
    int i = userRoleMapper.deleteUserRoleByUserId(userId);
    if (i >= 0) {
      i = userRoleMapper.insertRoleIds(userId, roleIds);
    }
    return i;
  }
}
